跳到主要内容
Cowers://
全部文章
推理范式

Self-Ask 自问自答多跳推理

Self-Ask 让模型在回答前显式地写出「我还需要先知道什么」,把一个复杂问题拆成一串子问题,逐个回答,最后合成终答。它管的是「问题分解」这一层控制流。

Self-Ask:自问自答的多跳推理

阅读提示 面向了解 Chain-of-Thought(CoT,思维链)和基础 RAG 检索的学习者。 本篇重点解释 Self-Ask 与 CoT 的机制差异,以及它为什么天然适合接搜索引擎。 ⚠️ = 常见陷阱 🆚 = 对比说明 💡 = 选择建议

目录


核心概念 Self-Ask 让模型在回答前显式地写出「我还需要先知道什么」,把一个复杂问题拆成一串子问题,逐个回答,最后合成终答。它管的是「问题分解」这一层控制流。

一、一句话定义

遇到复杂问题时,先不断问自己一些更简单的问题,逐个答完再合成最终答案。

二、最小示例:一次三跳推理

问题:

爱因斯坦出生城市所在国家的首都是哪里?

模型不直接作答,而是走这样一段 trace(对应原论文英文模板 Are follow up questions needed here: / Follow up: / Intermediate answer: / So the final answer is:):

需要追问吗:是            ← 只在开头出现这一次
 
追问:爱因斯坦出生在哪里?
中间答案:Ulm(乌尔姆)
 
追问:Ulm 在哪个国家?
中间答案:德国
 
追问:德国的首都是哪里?
中间答案:柏林
 
所以最终答案是:柏林      ← 靠这一行收尾,不是靠再问一次「需要追问吗」

结构:

复杂问题

「需要追问吗:是」            ← 一次性判断,之后不再重复

Follow up → Intermediate answer

Follow up → Intermediate answer     (循环若干次)

「所以最终答案是:」          ← 终止信号

⚠️ 以为每轮都要问一次「需要追问吗」 错误操作: 把循环写成「生成追问 → 回答 → 再问一次『需要追问吗:是/否』→ 为否则退出」,程序去检测那个「否」。

实际结果: 模型在拆解过程中不会再输出「需要追问吗:否」——它会直接输出 So the final answer is:。于是你的终止检测永远等不到信号,循环靠 max_steps 兜底截断,或者把最终答案当成又一个中间答案继续往下问。

(补一句精确的:开头那次判断,模型可以No 然后直接给答案——机制上是允许的。只是原论文官方 demo 的四个少样本示例全是 Yes 路径,没给过 No 的样子,所以模型极少走那条分支;官方代码也只是靠"最后一行还有没有 Follow up:"来退出循环,并没有专门处理 No别把「不会出现 No」当成协议保证,但也别把它当终止信号来解析。

原因: 在原论文的模板里,Are follow up questions needed here: 只在问题开头出现一次,用来决定「这题到底要不要拆」。一旦进入拆解,控制流就由 Follow up:So the final answer is: 这两个标记接管——前者表示还要再问一跳,后者表示收尾。

正确做法: 解析时认两个标记:读到 追问:Follow up:)就再走一跳,读到 所以最终答案是:So the final answer is:)就停。开头那次「需要追问吗」只用来决定要不要进入 Self-Ask 流程。

三、🆚 和 CoT 的区别:结构化在哪

两者都是「一步步想」,差别在于中间产物的形态。

维度 Chain-of-Thought Self-Ask
中间产物 自由散文式推理 一问一答的固定结构
能否被程序解析 难,格式不定 易,按 追问:/中间答案: 切分
能否插入外部工具 几乎不能 能,每个子问题都是天然的检索入口
事实错误可见性 藏在长句里 明确落在某个「中间答案」上,好定位

关键洞察 Self-Ask 真正的贡献不是「让模型想得更细」,而是把隐式推理变成了有明确边界的槽位。有了槽位,外部系统才有插手的地方——这正是下一节的内容。

四、机制:为什么它天生适合接搜索

因为每个「追问」都是一个独立、自包含、可直接检索的问句。

Self-Ask + Search

流程变成:

模型生成到「追问:爱因斯坦出生在哪里?」这一行,就停止生成

程序拦截这个追问,直接丢给搜索引擎(不判断模型确不确定)

search("爱因斯坦出生在哪里?") → "Ulm, Germany"

把检索结果作为「中间答案」写回上下文,让模型接着往下生成

模型生成下一个追问……

⚠️ 以为搜索是「模型不确定时才调」 错误操作: 实现时加一层判断——先让模型自己答,答得不确定(低置信度、说「我不清楚」)才去检索。

实际结果: 这层判断本身就不可靠。LLM 对自己编造的事实往往表现得非常确定,恰恰是幻觉最严重的那些答案最不会触发检索。于是该查的没查,不该查的查了一堆。

原因: 原论文的 Self-Ask + Search Engine 实现没有这个分支:每一个生成出来的 follow-up 都交给搜索引擎回答,用检索结果替代模型自己的中间答案。它的价值主张就是「别信模型的记忆,每一跳都去查」。

正确做法: 默认全查。工程上要省钱可以加缓存、或按问题类型(事实型 vs 计算型)分流,但不要用模型的自评置信度当开关

对比一下直接检索原问题会发生什么:

search("爱因斯坦出生城市所在国家的首都")
→ 命中的多是爱因斯坦传记页面,很难命中"柏林"

组合爆炸问题 多跳问题的字面表述在语料里往往根本不存在——没人会写一篇标题叫「爱因斯坦出生城市所在国家的首都」的文档。但拆开后的每一跳(「爱因斯坦出生地」「德国首都」)都是高频、易检索的事实。Self-Ask 把一次检索不到的复合查询,变成了三次都能检索到的简单查询。这就是它在 Multi-hop QA(多跳问答)上有效的根本原因。

五、⚠️ 核心陷阱:子问题跑偏且无人纠正

⚠️ 错误沿着链条放大 错误操作: 信任每个中间答案,直接拿去构造下一个追问,全程不校验。

实际结果:

追问 1:爱因斯坦出生在哪里?
中间答案:Bern(伯尔尼)        ← 错了,这是他工作过的城市
 
追问 2:Bern 在哪个国家?
中间答案:瑞士                   ← 这一跳本身完全正确
 
追问 3:瑞士首都是哪里?
中间答案:伯尔尼
 
最终答案:伯尔尼                 ← 错,且推理过程看起来毫无破绽

原因: Self-Ask 是串行依赖结构,第 N 跳的问题由第 N-1 跳的答案构造。第一跳错了之后,后面每一跳都在正确地回答一个错误的问题。而且因为每步局部自洽,最终输出读起来极具说服力——比一段含糊的 CoT 更容易骗过人。

正确做法: 三选一或组合:

  1. 给事实型子问题接检索,不靠模型记忆(最有效);
  2. 中间答案带来源,人和程序都能核;
  3. 关键跳做一致性校验——换个问法再问一次,两次不一致就标记存疑。

⚠️ 简单问题被强行拆解 错误操作: 对所有问题统一套 Self-Ask 模板。

实际结果: 问「Python 的 len() 返回什么」,模型也认真拆出三个追问,token 成本翻三倍,还多了三个出错机会。

原因: 拆解只在「原问题无法被一次检索/一次回忆解决」时才有收益。单跳问题拆解纯属负担。

正确做法: 在少样本示例里补上单跳的例子——需要追问吗:否 后面直接跟 所以最终答案是:…。原论文的示例全是多跳,模型看不到「可以不拆」的样板,就会对什么都拆。开头那次「需要追问吗」正是成本闸门,但它只有在示例里出现过「否」的走法时才真正起作用。

六、什么时候用

用:

  • Multi-hop QA(多跳问答):答案要串联两个以上事实
  • RAG 场景中,用户问题过于复合、单次检索召回差
  • 需要让推理链可审计、可溯源的场景

不用:

  • 单跳事实问答 → 直接答或直接检索
  • 需要探索多种方案(而非串联多个事实)的问题 → 那是 ToT 的领域

💡 Self-Ask 与 ToT 的分工 Self-Ask 是串行的:Q1 → Q2 → Q3,每步只有一条路,答完就往前走。 ToT 是并行的:同一步同时铺开多个候选,评估后剪枝。 判断方法:「我缺的是信息」→ Self-Ask;「我缺的是思路」→ ToT。

七、复习重点

复习重点

  1. 定义:显式写出追问 → 逐个回答 → 合成终答。
  2. 控制流的真相:「需要追问吗」只在开头判一次;循环由 追问: 推进、由 所以最终答案是: 终止。别去检测一个不会出现的「需要追问吗:否」。
  3. 与 CoT 的差别:不是想得更细,而是把推理变成可解析的槽位,从而给外部工具留出插入点。
  4. 为什么配搜索有效:复合问题的字面表述在语料里不存在,拆开后每一跳都是高频可检索事实。原实现是每个 follow-up 都查,不看模型置信度。
  5. 最危险的坑:串行依赖导致错误放大,且每步局部自洽、外观可信。对策是给事实型子问题接检索、带来源、做一致性校验。
  6. 第二个坑:别对单跳问题强行拆解——要在少样本示例里补上「不拆」的样板,闸门才生效。
  7. 它管哪一层:问题分解。缺信息用 Self-Ask,缺思路用 ToT,缺步骤规划用 Plan-and-Execute

相关笔记:Agent 推理范式总览Plan-and-Execute 先规划再执行Reflexion 反思式自我纠错ToT 思维树